import random
import string

from flask import Blueprint, render_template, request, jsonify, redirect, url_for,session
from exts import mail, db
from flask_mail import Message

from models import EmailCaptchaModel, UserModel

from .forms import RegisterForm,LoginForm
# 密码加密
from werkzeug.security import generate_password_hash,check_password_hash

# 创建对象:蓝图名称，和py文件名保持一致 + 固定写法，表示当前这个模块 + url前缀
bp = Blueprint("auth", __name__, url_prefix="/auth")


@bp.route("/login", methods = ['GET','POST'])
# 实际完整的url是/auth/login，bp对象已经指定前缀了，这里就可以省略
def login():
    if request.method == 'GET':
        return render_template("login.html")
    else:
        form = LoginForm(request.form)
        # 若验证通过
        if form.validate():
            #拿到提交去验证的数据的值
            email = form.email.data
            password = form.password.data
            # 在数据库中查找用户是否存在
            user = UserModel.query.filter_by(email = email).first()
            if not user :
                print("用户不存在")
                return redirect(url_for("auth.login"))
            # 用户存在，则验证密码
            # 导入check，判断“加密密码”解密后，是否等于“页面提交的密码”
            if check_password_hash(user.password, password):
                print("密码正确")
                # 使用cookie：cookie特点：只存放少量数据；有关登录授权的数据；
                # 使用前在config中设置secret_key，随意写入约20字符即可
                # 导入session：服务器会话技术
                session['user_id'] = user.id
                return redirect("/")
            else:
                print("密码错误")
                return redirect(url_for("auth.login"))
        else:
            return redirect(url_for("auth.login"))

# GET：从服务器上获取数据，此处渲染模板需要获取源代码数据，即使用GET
# 与此同时，还要向服务器提交数据，就要用POST
@bp.route("/register", methods=['GET', 'POST'])
def register():
    # 注册视图函数需要有以下两个功能
    # 1. 返回注册模板 2. 提交填入的信息
    if request.method == 'GET':
        return render_template("register.html")
    else:
        # html中的input标记都在form表单标记中，因此可以使用下列方法
        # RegisterForm是导入进来的类，request.form是提交的数据
        # 将提交的数据放入类中进行验证，返回form对象
        form = RegisterForm(request.form)
        # form.validate()：执行类中的所有验证，验证成功返回true
        if form.validate():
            # return "注册成功"，成功后就将这些提交的数据放入数据库：
            # 先获取数据
            email = form.email.data
            username = form.username.data
            password = form.password.data
            # 再放入数据库中(密码进行加密)
            user = UserModel(email=email, username=username, password=generate_password_hash(password))
            db.session.add(user)
            db.session.commit()
            # url_for("auth.login")可以自动找到/auth/login视图函数，转为url填充到redirect中
            return redirect(url_for("auth.login")) # 填def名！！而不是视图函数的名字
        else:
            # form.errors()
            # 失败回到注册页面
            return redirect(url_for("auth.register"))

@bp.route("/logout")
def logout():
    # 清掉session中的登录信息即可
    session.clear()
    return redirect("/")

@bp.route("/captcha/email")
def get_email_captcha():
    # 传参：1.路径传参2.查询字符串传参
    email = request.args.get("email")

    # string.digits是包含0~9的数组，digits = '0123456789'
    # 若直接在digits里取4位，采用的是不放回抽样，则不会存在相同数字
    # 因此将digits复制为4份，赋值给source变量，包含40个数字，此时0~9各存在4个，就可以抽出相同数字
    source = string.digits * 4
    # random随机，sample采样，在source中，采4位，赋值给captcha
    captcha = random.sample(source, 4)
    # 此时的captcha是数组类型，并非字符串，“分隔符”.join()可以将数组输出为以分隔符分隔的字符串
    captcha = "".join(captcha)
    # recipients=[email]：此时变量email存储了路径中的email参数
    message = Message(subject="邮箱验证码", recipients=[email], body="验证码：" + captcha)
    mail.send(message)

    # 为了后续验证码的校验，要短暂存储该验证码，如：memcached/redis
    # 为方便学习，此处使用数据库表存储验证码

    email_captcha = EmailCaptchaModel(email=email, captcha=captcha)
    db.session.add(email_captcha)
    db.session.commit()

    # 需要json格式的字符串
    return jsonify({"code": 200, "message": "", "data": None})


@bp.route("/mail/test")
def mail_test():
    message = Message(subject="邮箱测试", recipients=["3269376852@qq.com"], body="这是测试邮件")  # Message内容要有：标题+收件人+内容
    mail.send(message)
    return "邮件发送成功"
